package cn.wujiangbo.task;

import cn.wujiangbo.Thread.ReadExcelRunnable;
import cn.wujiangbo.service.IUserService;
import cn.wujiangbo.utils.MyTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import java.io.File;
import java.util.List;
import java.util.concurrent.*;

/**
 * 读取Excel入库操作（采用线程池技术）
 */
//@Component
public class ReadExcelThreadPoolTask {

    @Autowired
    private IUserService userService;

    /**
     * IO密集型任务 = 一般为2*CPU核心数（常出现于线程中：数据库数据交互、文件上传下载、网络数据传输等等）
     * CPU密集型任务 = 一般为CPU核心数+1（常出现于线程中：复杂算法）
     * 混合型任务 = 根据机器配置和复杂度自测而定
     */
    private static int corePoolSize = Runtime.getRuntime().availableProcessors();

    //自定义线程池
    private static ThreadPoolExecutor executor = new ThreadPoolExecutor(
            corePoolSize, //指定核心线程数量
            2 * corePoolSize, //指定最大线程数
            10L, //指定线程空闲后的最大存活时间
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(), //任务较多时暂存到此队列（无界队列）
            new ThreadPoolExecutor.DiscardPolicy() //策略：丢弃任务
    );

    //每X秒运行一次
    @Scheduled(cron = "0/20 * * * * *")
    public void readExcelTask() {
        System.out.println("corePoolSize=" + corePoolSize);
        String filePath = "E:/excel";
        //先获取指定路径下的所有需要读取的Excel文件的全路径，如：E:\excel\testExcel_175920.xlsx
        List<String> folderFile = MyTools.getFolderFile(filePath);
        if(null != folderFile && folderFile.size() > 0){
            long t1 = System.currentTimeMillis();
            CountDownLatch latch = new CountDownLatch(folderFile.size());
            for(int i=0; i<folderFile.size(); i++){
                String excelFilePath = folderFile.get(i);
                File file = new File(excelFilePath);
                if(file.exists()){
                    //文件存在就读取并入库
                    //execute：向线程池中添加一个任务
                    executor.execute(new ReadExcelRunnable(userService, excelFilePath, latch));
                }
            }
            try {
                latch.await();//等待所有线程执行完成之后，再统计执行时间
                long t2 = System.currentTimeMillis();
                System.out.println("总耗时：" + (t2-t1) + "毫秒");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        else{
            System.out.println("目录 [" + filePath + "] 中没有Excel文件啦.......");
        }
    }
}